package com.asm.controller;

import com.asm.pojo.SnvCpgAll;
import com.asm.service.SNV2TfCHIPseqService;
import com.asm.service.SnvCpgAllService;
import com.asm.util.DatatableResult;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.lang.reflect.Field;
import java.util.*;

@CrossOrigin
@RestController
@RequestMapping("/download")
public class Download {
    private static final Logger logger = LoggerFactory.getLogger(Download.class);
    
    @Autowired
    private SnvCpgAllService snvCpgAllService;

    private final String FILE_DIRECTORY = "/home/CanASM/runfile/download/"; // 文件存储的基础目录

    @GetMapping("/file")
    public ResponseEntity<Resource> downloadFile(@RequestParam("filePath") String filePath) {
        logger.info("请求下载文件: {}", filePath);
        
        try {
            // 解码URL编码的文件路径
            filePath = java.net.URLDecoder.decode(filePath, StandardCharsets.UTF_8.name());
            logger.info("解码后的文件路径: {}", filePath);
            
            // 处理文件路径
            Path fullPath;
            
            // 移除路径中的特殊字符和不安全字符
            filePath = filePath.replace("%2F", "/").replace("%20", " ");
            
            if (filePath.contains(":\\") || filePath.startsWith("/")) {
                // 如果是绝对路径，直接使用
                fullPath = Paths.get(filePath).normalize();
                logger.info("使用绝对路径: {}", fullPath);
            } else {
                // 如果是相对路径或纯文件名，拼接基础目录
                fullPath = Paths.get(FILE_DIRECTORY, filePath).normalize();
                logger.info("使用相对路径，完整路径: {}", fullPath);
            }
            
            // 检查文件是否存在
            File file = fullPath.toFile();
            if (!file.exists()) {
                logger.error("文件不存在: {}", fullPath);
                
                // 尝试列出基础目录中的文件，帮助调试
                try {
                    File baseDir = new File(FILE_DIRECTORY);
                    logger.info("基础目录 {} 是否存在: {}", FILE_DIRECTORY, baseDir.exists());
                    if (baseDir.exists() && baseDir.isDirectory()) {
                        logger.info("基础目录内容:");
                        for (File f : baseDir.listFiles()) {
                            logger.info(" - {}", f.getName());
                        }
                    }
                } catch (Exception e) {
                    logger.error("列出基础目录内容时出错", e);
                }
                
                return ResponseEntity.notFound().build();
            }
            
            // 安全检查：确保文件在基础目录内
            String baseDirPath = Paths.get(FILE_DIRECTORY).toAbsolutePath().toString();
            String requestedFilePath = fullPath.toAbsolutePath().toString();
            logger.info("基础目录路径: {}", baseDirPath);
            logger.info("请求的文件路径: {}", requestedFilePath);
            
            if (!requestedFilePath.startsWith(baseDirPath)) {
                logger.error("安全检查失败：请求的文件不在基础目录内");
                return ResponseEntity.badRequest().body(null);
            }
            
            Resource resource = new UrlResource(fullPath.toUri());
            logger.info("创建资源: {}", resource.getURI());

            // 检查文件是否可读
            if (!resource.isReadable()) {
                logger.error("文件不可读: {}", fullPath);
                return ResponseEntity.notFound().build();
            }

            // 获取文件名（不包含路径）
            String fileName = fullPath.getFileName().toString();
            logger.info("文件名: {}", fileName);
            
            // 设置响应头
            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"");
            
            // 根据文件扩展名设置Content-Type
            String contentType = determineContentType(fileName);
            headers.add(HttpHeaders.CONTENT_TYPE, contentType);
            logger.info("Content-Type: {}", contentType);
            
            // 设置文件大小
            long fileSize = Files.size(fullPath);
            logger.info("文件大小: {} 字节", fileSize);

            // 返回文件
            return ResponseEntity.ok()
                    .headers(headers)
                    .contentLength(fileSize)
                    .body(resource);

        } catch (MalformedURLException e) {
            logger.error("URL格式错误", e);
            return ResponseEntity.badRequest().build();
        } catch (IOException e) {
            logger.error("IO异常", e);
            return ResponseEntity.status(500).build();
        } catch (Exception e) {
            logger.error("下载文件时发生未知错误", e);
            return ResponseEntity.status(500).build();
        }
    }
    
    /**
     * 根据文件扩展名确定Content-Type
     */
    private String determineContentType(String fileName) {
        String extension = "";
        int i = fileName.lastIndexOf('.');
        if (i > 0) {
            extension = fileName.substring(i + 1).toLowerCase();
        }
        
        switch (extension) {
            case "pdf":
                return "application/pdf";
            case "doc":
            case "docx":
                return "application/msword";
            case "xls":
            case "xlsx":
                return "application/vnd.ms-excel";
            case "ppt":
            case "pptx":
                return "application/vnd.ms-powerpoint";
            case "jpg":
            case "jpeg":
                return "image/jpeg";
            case "png":
                return "image/png";
            case "txt":
                return "text/plain";
            default:
                return MediaType.APPLICATION_OCTET_STREAM_VALUE;
        }
    }

    @GetMapping("/snv_cpg")
    public ResponseEntity<Resource> snvCpgAllList(
            @RequestParam("tissue") String tissue){
        
        logger.info("请求下载SNV-CpG数据，组织: {}", tissue);
        
        try {
            // 查询数据
            List<SnvCpgAll> list = snvCpgAllService.selectAllSnvCpgAll(tissue, null, null, null, null, null, null);
            logger.info("查询到 {} 条记录", list.size());
            
            // 生成文件名
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
            String timestamp = dateFormat.format(new Date());
            String fileName = "snv_cpg_" + tissue + "_" + timestamp + ".csv";
            
            // 直接在内存中构建CSV内容
            StringBuilder csvContent = new StringBuilder();
            
            // 添加CSV头部
            csvContent.append("Index SNV,Chr,CpG pos,p-value,q-value,Ref,Observe,Sample,Tissue,Sample type\n");
            
            // 添加数据行
            for (SnvCpgAll item : list) {
                csvContent.append(nullSafe(item.getIdInDbsnp())).append(",");
                csvContent.append(nullSafe(item.getChr())).append(",");
                csvContent.append(nullSafe(item.getCpgPos())).append(",");
                csvContent.append(nullSafe(item.getPValue())).append(",");
                csvContent.append(nullSafe(item.getqValue())).append(",");
                csvContent.append(nullSafe(item.getRefInDbsnp())).append(",");
                csvContent.append(nullSafe(item.getAlternateAllele())).append(",");
                csvContent.append(nullSafe(item.getSample())).append(",");
                csvContent.append(nullSafe(item.getSampleInfo().getTissue())).append(",");
                csvContent.append(nullSafe(item.getSampleInfo().getSampleType())).append("\n");
            }
            
            // 将内容转换为字节数组
            byte[] csvBytes = csvContent.toString().getBytes(StandardCharsets.UTF_8);
            
            // 创建资源
            ByteArrayResource resource = new ByteArrayResource(csvBytes);
            
            logger.info("CSV数据生成成功，大小: {} 字节", csvBytes.length);
            
            // 返回文件下载响应
            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"")
                    .contentType(MediaType.parseMediaType("text/csv; charset=UTF-8"))
                    .contentLength(csvBytes.length)
                    .body(resource);
                    
        } catch (Exception e) {
            logger.error("生成CSV数据时发生错误", e);
            return ResponseEntity.status(500).build();
        }
    }
    
    /**
     * 安全处理可能为null的值
     */
    private String nullSafe(Object obj) {
        if (obj == null) {
            return "";
        }
        // 处理逗号，防止CSV格式错误
        return obj.toString().replace(",", ";");
    }
}
